"""事件处理器

管理实时事件、通知和响应机制。
"""

import logging
import threading
import queue
import time
import json
from typing import Dict, List, Any, Optional, Callable
from datetime import datetime, timedelta
from enum import Enum
from dataclasses import dataclass, asdict
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart

class EventType(Enum):
    """事件类型枚举"""
    DATA_ANOMALY = "data_anomaly"
    SYSTEM_ALERT = "system_alert"
    THRESHOLD_EXCEEDED = "threshold_exceeded"
    DATA_QUALITY_ISSUE = "data_quality_issue"
    TREND_CHANGE = "trend_change"
    PROCESSING_ERROR = "processing_error"
    USER_ACTION = "user_action"
    CUSTOM = "custom"

class EventSeverity(Enum):
    """事件严重程度枚举"""
    LOW = "low"
    MEDIUM = "medium"
    HIGH = "high"
    CRITICAL = "critical"

@dataclass
class Event:
    """事件数据类"""
    event_id: str
    event_type: EventType
    severity: EventSeverity
    title: str
    message: str
    timestamp: datetime
    source: str
    data: Dict[str, Any]
    tags: List[str]
    resolved: bool = False
    resolution_time: Optional[datetime] = None
    resolution_notes: str = ""
    
    def to_dict(self) -> Dict[str, Any]:
        """转换为字典"""
        result = asdict(self)
        result['event_type'] = self.event_type.value
        result['severity'] = self.severity.value
        result['timestamp'] = self.timestamp.isoformat()
        if self.resolution_time:
            result['resolution_time'] = self.resolution_time.isoformat()
        return result

class EventHandler:
    """事件处理器"""
    
    def __init__(self, max_events: int = 1000):
        """
        初始化事件处理器
        
        Args:
            max_events: 最大事件数量
        """
        self.logger = logging.getLogger(__name__)
        self.max_events = max_events
        
        # 事件存储
        self.events = []
        self.event_queue = queue.Queue()
        
        # 事件处理器映射
        self.event_handlers = {}
        self.global_handlers = []
        
        # 通知配置
        self.notification_config = {
            'email': {
                'enabled': False,
                'smtp_server': '',
                'smtp_port': 587,
                'username': '',
                'password': '',
                'recipients': []
            },
            'webhook': {
                'enabled': False,
                'url': '',
                'headers': {}
            }
        }
        
        # 过滤规则
        self.filters = []
        
        # 运行状态
        self.is_running = False
        self.processing_thread = None
        
        # 统计信息
        self.stats = {
            'total_events': 0,
            'events_by_type': {},
            'events_by_severity': {},
            'resolved_events': 0,
            'last_event_time': None
        }
        
        # 事件ID计数器
        self._event_counter = 0
        self._counter_lock = threading.Lock()
    
    def start(self):
        """
        启动事件处理器
        """
        if self.is_running:
            self.logger.warning("事件处理器已在运行")
            return
        
        self.is_running = True
        self.processing_thread = threading.Thread(target=self._processing_loop)
        self.processing_thread.daemon = True
        self.processing_thread.start()
        
        self.logger.info("事件处理器已启动")
    
    def stop(self):
        """
        停止事件处理器
        """
        self.is_running = False
        
        if self.processing_thread:
            self.processing_thread.join(timeout=5)
        
        self.logger.info("事件处理器已停止")
    
    def emit_event(self, event_type: EventType, severity: EventSeverity, 
                   title: str, message: str, source: str = "system", 
                   data: Optional[Dict[str, Any]] = None, 
                   tags: Optional[List[str]] = None) -> str:
        """
        发出事件
        
        Args:
            event_type: 事件类型
            severity: 严重程度
            title: 事件标题
            message: 事件消息
            source: 事件源
            data: 附加数据
            tags: 标签
            
        Returns:
            事件ID
        """
        try:
            # 生成事件ID
            with self._counter_lock:
                self._event_counter += 1
                event_id = f"evt_{self._event_counter}_{int(time.time())}"
            
            # 创建事件
            event = Event(
                event_id=event_id,
                event_type=event_type,
                severity=severity,
                title=title,
                message=message,
                timestamp=datetime.now(),
                source=source,
                data=data or {},
                tags=tags or []
            )
            
            # 应用过滤器
            if self._should_process_event(event):
                self.event_queue.put(event)
                self.logger.debug(f"事件已发出: {event_id}")
            else:
                self.logger.debug(f"事件被过滤: {event_id}")
            
            return event_id
            
        except Exception as e:
            self.logger.error(f"发出事件失败: {e}")
            return ""
    
    def add_event_handler(self, event_type: EventType, 
                         handler: Callable[[Event], None]):
        """
        添加事件处理器
        
        Args:
            event_type: 事件类型
            handler: 处理函数
        """
        if event_type not in self.event_handlers:
            self.event_handlers[event_type] = []
        
        self.event_handlers[event_type].append(handler)
        self.logger.info(f"已添加 {event_type.value} 事件处理器")
    
    def add_global_handler(self, handler: Callable[[Event], None]):
        """
        添加全局事件处理器
        
        Args:
            handler: 处理函数
        """
        self.global_handlers.append(handler)
        self.logger.info("已添加全局事件处理器")
    
    def add_filter(self, filter_func: Callable[[Event], bool]):
        """
        添加事件过滤器
        
        Args:
            filter_func: 过滤函数，返回True表示处理事件
        """
        self.filters.append(filter_func)
        self.logger.info("已添加事件过滤器")
    
    def resolve_event(self, event_id: str, resolution_notes: str = ""):
        """
        解决事件
        
        Args:
            event_id: 事件ID
            resolution_notes: 解决说明
        """
        try:
            for event in self.events:
                if event.event_id == event_id and not event.resolved:
                    event.resolved = True
                    event.resolution_time = datetime.now()
                    event.resolution_notes = resolution_notes
                    
                    self.stats['resolved_events'] += 1
                    self.logger.info(f"事件已解决: {event_id}")
                    return
            
            self.logger.warning(f"未找到事件或事件已解决: {event_id}")
            
        except Exception as e:
            self.logger.error(f"解决事件失败: {e}")
    
    def get_events(self, event_type: Optional[EventType] = None, 
                   severity: Optional[EventSeverity] = None,
                   resolved: Optional[bool] = None,
                   limit: int = 100) -> List[Event]:
        """
        获取事件列表
        
        Args:
            event_type: 事件类型过滤
            severity: 严重程度过滤
            resolved: 解决状态过滤
            limit: 限制数量
            
        Returns:
            事件列表
        """
        filtered_events = self.events
        
        # 应用过滤条件
        if event_type is not None:
            filtered_events = [e for e in filtered_events if e.event_type == event_type]
        
        if severity is not None:
            filtered_events = [e for e in filtered_events if e.severity == severity]
        
        if resolved is not None:
            filtered_events = [e for e in filtered_events if e.resolved == resolved]
        
        # 按时间倒序排列
        filtered_events.sort(key=lambda x: x.timestamp, reverse=True)
        
        return filtered_events[:limit]
    
    def get_event_stats(self) -> Dict[str, Any]:
        """
        获取事件统计信息
        
        Returns:
            统计信息
        """
        current_stats = self.stats.copy()
        
        # 计算实时统计
        current_stats['unresolved_events'] = len([e for e in self.events if not e.resolved])
        current_stats['events_last_hour'] = len([
            e for e in self.events 
            if e.timestamp > datetime.now() - timedelta(hours=1)
        ])
        current_stats['events_last_day'] = len([
            e for e in self.events 
            if e.timestamp > datetime.now() - timedelta(days=1)
        ])
        
        return current_stats
    
    def configure_email_notifications(self, smtp_server: str, smtp_port: int,
                                    username: str, password: str,
                                    recipients: List[str]):
        """
        配置邮件通知
        
        Args:
            smtp_server: SMTP服务器
            smtp_port: SMTP端口
            username: 用户名
            password: 密码
            recipients: 收件人列表
        """
        self.notification_config['email'].update({
            'enabled': True,
            'smtp_server': smtp_server,
            'smtp_port': smtp_port,
            'username': username,
            'password': password,
            'recipients': recipients
        })
        
        self.logger.info("邮件通知已配置")
    
    def configure_webhook_notifications(self, url: str, 
                                      headers: Optional[Dict[str, str]] = None):
        """
        配置Webhook通知
        
        Args:
            url: Webhook URL
            headers: 请求头
        """
        self.notification_config['webhook'].update({
            'enabled': True,
            'url': url,
            'headers': headers or {}
        })
        
        self.logger.info("Webhook通知已配置")
    
    def _processing_loop(self):
        """
        事件处理循环
        """
        while self.is_running:
            try:
                # 获取事件
                try:
                    event = self.event_queue.get(timeout=1)
                except queue.Empty:
                    continue
                
                # 处理事件
                self._process_event(event)
                
                # 标记任务完成
                self.event_queue.task_done()
                
            except Exception as e:
                self.logger.error(f"事件处理循环错误: {e}")
                time.sleep(0.1)
    
    def _process_event(self, event: Event):
        """
        处理单个事件
        
        Args:
            event: 事件对象
        """
        try:
            # 存储事件
            self.events.append(event)
            
            # 维护事件数量限制
            if len(self.events) > self.max_events:
                self.events = self.events[-self.max_events:]
            
            # 更新统计
            self._update_stats(event)
            
            # 调用特定类型的处理器
            if event.event_type in self.event_handlers:
                for handler in self.event_handlers[event.event_type]:
                    try:
                        handler(event)
                    except Exception as e:
                        self.logger.error(f"事件处理器执行失败: {e}")
            
            # 调用全局处理器
            for handler in self.global_handlers:
                try:
                    handler(event)
                except Exception as e:
                    self.logger.error(f"全局事件处理器执行失败: {e}")
            
            # 发送通知
            self._send_notifications(event)
            
            self.logger.debug(f"事件处理完成: {event.event_id}")
            
        except Exception as e:
            self.logger.error(f"处理事件失败: {e}")
    
    def _should_process_event(self, event: Event) -> bool:
        """
        检查是否应该处理事件
        
        Args:
            event: 事件对象
            
        Returns:
            是否处理
        """
        try:
            for filter_func in self.filters:
                if not filter_func(event):
                    return False
            return True
            
        except Exception as e:
            self.logger.error(f"事件过滤失败: {e}")
            return True  # 默认处理
    
    def _update_stats(self, event: Event):
        """
        更新统计信息
        
        Args:
            event: 事件对象
        """
        try:
            self.stats['total_events'] += 1
            self.stats['last_event_time'] = event.timestamp
            
            # 按类型统计
            event_type_str = event.event_type.value
            if event_type_str not in self.stats['events_by_type']:
                self.stats['events_by_type'][event_type_str] = 0
            self.stats['events_by_type'][event_type_str] += 1
            
            # 按严重程度统计
            severity_str = event.severity.value
            if severity_str not in self.stats['events_by_severity']:
                self.stats['events_by_severity'][severity_str] = 0
            self.stats['events_by_severity'][severity_str] += 1
            
        except Exception as e:
            self.logger.error(f"更新统计失败: {e}")
    
    def _send_notifications(self, event: Event):
        """
        发送通知
        
        Args:
            event: 事件对象
        """
        try:
            # 只对高严重程度事件发送通知
            if event.severity in [EventSeverity.HIGH, EventSeverity.CRITICAL]:
                # 发送邮件通知
                if self.notification_config['email']['enabled']:
                    self._send_email_notification(event)
                
                # 发送Webhook通知
                if self.notification_config['webhook']['enabled']:
                    self._send_webhook_notification(event)
            
        except Exception as e:
            self.logger.error(f"发送通知失败: {e}")
    
    def _send_email_notification(self, event: Event):
        """
        发送邮件通知
        
        Args:
            event: 事件对象
        """
        try:
            config = self.notification_config['email']
            
            # 创建邮件
            msg = MIMEMultipart()
            msg['From'] = config['username']
            msg['To'] = ', '.join(config['recipients'])
            msg['Subject'] = f"[SurveyAnalyzer] {event.severity.value.upper()}: {event.title}"
            
            # 邮件内容
            body = f"""
事件通知

事件ID: {event.event_id}
事件类型: {event.event_type.value}
严重程度: {event.severity.value}
时间: {event.timestamp.strftime('%Y-%m-%d %H:%M:%S')}
来源: {event.source}

标题: {event.title}
消息: {event.message}

标签: {', '.join(event.tags)}

详细信息:
{json.dumps(event.data, ensure_ascii=False, indent=2)}

---
SurveyAnalyzer 自动通知系统
            """
            
            msg.attach(MIMEText(body, 'plain', 'utf-8'))
            
            # 发送邮件
            server = smtplib.SMTP(config['smtp_server'], config['smtp_port'])
            server.starttls()
            server.login(config['username'], config['password'])
            server.send_message(msg)
            server.quit()
            
            self.logger.info(f"邮件通知已发送: {event.event_id}")
            
        except Exception as e:
            self.logger.error(f"发送邮件通知失败: {e}")
    
    def _send_webhook_notification(self, event: Event):
        """
        发送Webhook通知
        
        Args:
            event: 事件对象
        """
        try:
            import requests
            
            config = self.notification_config['webhook']
            
            # 准备数据
            payload = {
                'event': event.to_dict(),
                'notification_time': datetime.now().isoformat(),
                'source': 'SurveyAnalyzer'
            }
            
            # 发送请求
            response = requests.post(
                config['url'],
                json=payload,
                headers=config['headers'],
                timeout=10
            )
            
            if response.status_code == 200:
                self.logger.info(f"Webhook通知已发送: {event.event_id}")
            else:
                self.logger.warning(f"Webhook通知发送失败: {response.status_code}")
            
        except Exception as e:
            self.logger.error(f"发送Webhook通知失败: {e}")
    
    def export_events(self, filepath: str, event_type: Optional[EventType] = None,
                     start_time: Optional[datetime] = None,
                     end_time: Optional[datetime] = None):
        """
        导出事件数据
        
        Args:
            filepath: 导出文件路径
            event_type: 事件类型过滤
            start_time: 开始时间
            end_time: 结束时间
        """
        try:
            # 过滤事件
            filtered_events = self.events
            
            if event_type:
                filtered_events = [e for e in filtered_events if e.event_type == event_type]
            
            if start_time:
                filtered_events = [e for e in filtered_events if e.timestamp >= start_time]
            
            if end_time:
                filtered_events = [e for e in filtered_events if e.timestamp <= end_time]
            
            # 转换为字典格式
            events_data = [event.to_dict() for event in filtered_events]
            
            # 导出数据
            export_data = {
                'export_time': datetime.now().isoformat(),
                'total_events': len(events_data),
                'filters': {
                    'event_type': event_type.value if event_type else None,
                    'start_time': start_time.isoformat() if start_time else None,
                    'end_time': end_time.isoformat() if end_time else None
                },
                'events': events_data,
                'stats': self.get_event_stats()
            }
            
            with open(filepath, 'w', encoding='utf-8') as f:
                json.dump(export_data, f, ensure_ascii=False, indent=2)
            
            self.logger.info(f"事件数据已导出到: {filepath}")
            
        except Exception as e:
            self.logger.error(f"导出事件数据失败: {e}")

# 示例事件处理器
def log_event_handler(event: Event):
    """
    日志事件处理器
    
    Args:
        event: 事件对象
    """
    logger = logging.getLogger('event_handler')
    logger.info(f"[{event.severity.value.upper()}] {event.title}: {event.message}")

def critical_event_handler(event: Event):
    """
    关键事件处理器
    
    Args:
        event: 事件对象
    """
    if event.severity == EventSeverity.CRITICAL:
        logger = logging.getLogger('critical_handler')
        logger.critical(f"CRITICAL EVENT: {event.title} - {event.message}")
        # 这里可以添加更多的紧急响应逻辑

def severity_filter(event: Event) -> bool:
    """
    严重程度过滤器示例
    
    Args:
        event: 事件对象
        
    Returns:
        是否处理事件
    """
    # 只处理中等及以上严重程度的事件
    return event.severity in [EventSeverity.MEDIUM, EventSeverity.HIGH, EventSeverity.CRITICAL]